let str = new String("hdrcms.com");
console.log(str.substring(0, 1));

// 立即执行函数 其实就有一个私有的作用域或者用let

function sortArray(array, type = "asc") {
  return array.sort((a, b) => (type == "asc" ? a - b : b - a));
}
console.log(sortArray([3, 9, 1, 2]));

function sum(total, discount = 0, dis = 0) {
  return Math.round(total * (1 - discount) * (1 - dis));
}
console.log(sum(1000, 0.1, 0.2));

function sum(...args) {
  //   1.以往是这种方法
  //   let total = 0;
  //   for (let i = 0; i < arguments.length; i++) {
  //     total += arguments[i];
  //   }
  //   return total;
  //   return [...arguments].reduce((a, b) => a + b);
  //   2.现在可以用...语法, ...语法有收集和展开的功能
  return args.reduce((a, b) => a + b);
}

console.log(sum(1, 23, 42, 41, 32, 53, 64));

let hd = [1, 2, 3, 4, 5, 6].filter((item) => item <= 3);
console.log(hd);

// 阶层
function factorial(num) {
  return num == 1 ? 1 : num * factorial(num - 1);
}
console.log(factorial(5));

// 递归求和

function sum(...args) {
  return args.length == 0 ? 0 : args.pop() + sum(...args);
}
console.log(sum(1, 2, 3, 4, 5));

// 递归打印*
/*function star(sum) {
  return sum ? document.write("*".repeat(sum) + "<br/>") || star(--sum) : "";
}
star(5);*/

let hd1 = [1, 2, 3];
let [a, b, c] = [...hd];
console.log(a);
console.log([...hd1]);

let [f, ...edu] = [1, 2, 3, 4];
console.log(edu);

function colTotal(discount = 0, ...price) {
  let total = price.reduce((a, b) => a + b);
  return Math.round(total * (1 - discount));
}
console.log(colTotal(0.5, 1990, 2000, 1000));

// 函数方法与this不同
function User(name) {
  this.name = name;
  this.show = function () {
    // 只有是方法中的this才是当前对象的this, render并不是方法只是一个普通函数
    function render() {
      console.log(this); // 我是在node环境下跑的，如果你是在html下跑就是windows全局对象
    }
    render();
    return this.name;
  };
}

let lisi = new User("李四");
console.log(lisi.show());

let Lesson = {
  site: "后盾人",
  lists: ["js", "css", "mysql"],
  show: function () {
    return this.lists.map(function (val) {
      // 可以通过传递第二个参数来获取对象的this
      return `${this.site} - ${val}`;
    }, this);
  },
};

// console.table(Lesson.show());

// 箭头函数
let LessonOne = {
  site: "jason",
  lists: ["js", "css", "mysql"],
  show() {
    // 这里是用箭头函数，箭头函数本身没有this，它会往它的父级函数找this，那么show是LessonOne中的方法，所以this就是当前对象，因此箭头函数中的this就是志向当前函数
    return this.lists.map((val) => `${this.site} - ${val}`);
  },
};

console.table(LessonOne.show());

// apply call bind

function Person(name) {
  this.name = name;
}
let jason = new Person("jason");
console.log(jason);
let hdrcms = { url: "hdcms.com" };
Person.call(hdrcms, "开源系统"); // call改变this指向，第二参数是传给Person构造函数的形参, 它会立刻执行不需要再次调用
console.log(hdrcms);

// apply和call的不同之处
let arr = [1, 2, 3, 4, 5];
console.log(Math.max.apply(Math, arr));

let cf = {
  name: "cf",
};

let lol = {
  name: "lol",
};

function ShowTel(web, url) {
  console.log(web + url + this.name);
}

// 在于传递参数的不同 call之能用逗号隔开，apply可以使用数组传递多个值
ShowTel.call(cf, "cf官网", "cf.com");
ShowTel.apply(lol, ["lolguanwu", "lol.com"]);

function Request() {
  this.get = function (params) {
    // 获取对象的key值
    let str = Object.keys(params)
      .map((k) => `${k}=${params[k]}`)
      .join("&");
    let url = `https://api.houdunren.com?${this.url}/${str}`;
    console.log(url);
  };
}

function Article() {
  this.url = "article/lists";
  //  把当前this传递进去就是Article构造函数
  Request.call(this);
}

let articleData = new Article();
articleData.get({ id: 1, cat: "js" });

// bind 会返回一个函数，需要手动调用
function hd2(a, b) {
  console.log(a, b);
  return this.f + a + b;
}
let func = hd2.bind({ f: 1 }, 1); // 将1传递给了a，
func(3, 4); // a已经有了参数，所以3传递给了b，那么4就没有用了
